#!/usr/bin/python2.6
# -*- coding: utf-8 -*-

import types

import xml.dom.minidom
from xml.etree import ElementTree as ET

def XmlPrettyPrint(s):
    x = xml.dom.minidom.parseString(s)
    s = x.toprettyxml()
    print s

def ObjectToXmlElement(value):
    elem = ET.Element('o')

    if value == None:
        elem.set('type', 'none')
        elem.text = ''
    elif isinstance(value, str):
        elem.set('type', 'str')
        elem.text = unicode(value)
    elif isinstance(value, types.UnicodeType):
        elem.set('type', 'str')
        elem.text = unicode(value)
    elif isinstance(value, int):
        elem.set('type', 'int')
        elem.text = unicode(value)
    elif isinstance(value, float):
        elem.set('type', 'float')
        elem.text = unicode(value)
    elif isinstance(value, list):
        elem.set('type', 'list')
        for item in value:
            subElem = ObjectToXmlElement(item)
            elem.append(subElem)
    elif isinstance(value, dict):
        elem.set('type', 'dict')
        for (k, v) in value.items():
            itemElem = ET.Element('i')
            itemElem.set('name', k)
            valElem = ObjectToXmlElement(v)
            itemElem.append(valElem)
            elem.append(itemElem)
    else:
        raise Exception('Could not create xml element: unknown input value type (%s)!' % (type(value),))

    return elem

def ObjectToXmlDoc(value):
    root = ET.Element('xml')
    elem = ObjectToXmlElement(value)
    root.append(elem)
    return root

def XmlElementToObject(elem):
    if elem == None:
        raise Exception('Couldn\'t create object: elem == None!')

    if elem.tag != 'o':
        raise Exception('Unknown tag name: \'%s\'!' % (elem.tag,))

    t = elem.get('type')
    if t == 'none':
        return None
    elif t == 'str':
        return unicode(elem.text)
    elif t == 'int':
        return int(elem.text)
    elif t == 'float':
        return float(elem.text)
    elif t == 'list':
        return [XmlElementToObject(subElem) for subElem in elem]
    elif t == 'dict':
        l = []
        for subElem in elem:
            if subElem.tag != 'i':
                raise Exception('Couldn\'t create dict-object: wrong child-tag name (\'%s\')!' % (name,))
            name = subElem.get('name')
            val = XmlElementToObject(subElem.getchildren()[0])
            l.append([name, val])
        return dict(l)

        l = [[subElem.get('name'), XmlElementToObject(subElem.getchildren()[0])] for subElem in elem if subElem.tag != 'i']
        return dict(l)
    else:
        raise Exception('Couldn\'t create object: unknown object type (\'%s\')!' % (t,)) 

def XmlDocToObject(elem):
    if elem == None:
        raise Exception('Couldn\'t create object from xml-doc: elem == None!')

    if elem.tag != 'xml':
        raise Exception('Couldn\'t create object from xml-doc: wront root name (\'%s\')!' % (elem.tag,))

    return [XmlElementToObject(subElem) for subElem in elem]

###################

def CreateXmlRequest(methodName, args):
    if not isinstance(methodName, str):
        raise Exception('Couldn\'t create xml-request: methodName should be instance of str type, but it is \'%s\'!' % (type(methodName),))

    if not isinstance(args, dict):
        raise Exception('Couldn\'t create xml-request: args should be instance of dict type, but it is \'%s\'!' % (type(args),))

    return ObjectToXmlDoc({'methodName': methodName, 'args': args})

def ParseXmlRequest(root):
    obj = XmlDocToObject(root)
    obj = obj[0]
    if not isinstance(obj, dict):
        raise Exception('Couldn\'t parse xml-request: xml-document should contain dict object, but it contains \'%s\'!' % (type(obj),))
    return obj
        
def CreateXmlResponse(status, data):
    if not isinstance(status, str):
        raise Exception('Couldn\'t create xml-response: status should be instance of str type, but it is \'%s\'!' % (type(status),))
    return ObjectToXmlDoc({'status': status, 'data': data})

def ParseXmlResponse(root):
    obj = XmlDocToObject(root)
    obj = obj[0]
    if not isinstance(obj, dict):
        raise Exception('Couldn\'t parse xml-response: xml-document should contain dict object, but it contains \'%s\'!' % (type(obj),))
    return obj
